﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using DeferredWaterDemo;

namespace Demo
{
    public partial class Render
    {
        static SpriteBatch sprite;
        public static VertexDeclaration _declEngine;
        static VertexDeclaration _declLighting;
 
        static VertexBuffer screenQuad;

        public static VertexDeclaration GeometryVertex
        {
            get
            {
                if (_declEngine == null)
                    _declEngine = new VertexDeclaration(graphics, new VertexElement[] 
                    {
                       new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
                       new VertexElement(0, 12, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0),
                       new VertexElement(0, 24, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Tangent, 0),
                       new VertexElement(0, 36, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0),
                       new VertexElement(0, 44, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 1),
                       new VertexElement(0, 52, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.BlendWeight, 0),
                       new VertexElement(0, 68, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.BlendIndices, 0),
                    });

                return _declEngine;
            }
        }

        public static VertexDeclaration ScreenVertex
        {
            get
            {
                if (_declLighting == null)
                    _declLighting = new VertexDeclaration(graphics, VertexPositionTexture.VertexElements);
                return _declLighting;
            }
        } 

        public static SpriteBatch Sprites
        {
            get
            {
                return sprite;
            }
        }

        public static RenderTarget2D CreateRenderTarget(GraphicsDevice device,
            int numberLevels, SurfaceFormat surface)
        { 

            if (!GraphicsAdapter.DefaultAdapter.CheckDeviceFormat(DeviceType.Hardware,
                GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Format, TextureUsage.None,
                QueryUsages.None,ResourceType.RenderTarget, surface)) {

                surface = device.DisplayMode.Format;
            } 

            int width = device.PresentationParameters.BackBufferWidth;
            int height = device.PresentationParameters.BackBufferHeight;

            CheckTextureSize(ref width, ref height);

            return new RenderTarget2D(device, width, height, numberLevels, surface, MultiSampleType.None, 0);
        }

        public static void CheckTextureSize(ref int width, ref int height)
        {
            GraphicsDeviceCapabilities Caps;
            Caps = GraphicsAdapter.DefaultAdapter.GetCapabilities(
                DeviceType.Hardware);

            if (Caps.TextureCapabilities.RequiresPower2)
            {
                double exp = Math.Ceiling(Math.Log(width) / Math.Log(2));
                width = (int)Math.Pow(2, exp);
                exp = Math.Ceiling(Math.Log(height) / Math.Log(2));
                height = (int)Math.Pow(2, exp);
            }
            if (Caps.TextureCapabilities.RequiresSquareOnly)
            {
                width = Math.Max(width, height);
                height = width;
            }

            width = Math.Min(Caps.MaxTextureWidth, width);
            height = Math.Min(Caps.MaxTextureHeight, height);
        }

        public static bool GetScreenPosition(Vector3 world, out Vector2 screen) {

            Vector3 t =
                graphics.Viewport.Project(world,
                Core.Camera.Projection,
                Core.Camera.View, 
                Matrix.Identity);

            screen.X = t.X;
            screen.Y = t.Y;
            return t.Z < 1f;
        }
    }
}
